﻿package {
	import alternativa.engine3d.materials.FillMaterial;
	import alternativa.engine3d.materials.TextureMaterial;
	import alternativa.types.Texture;
	
	import flash.geom.Point;
	
	public class TexturedHouse extends House {
		
		[Embed(source="resources/wall.jpg")] private static const bmpWall:Class;
		[Embed(source="resources/roof.jpg")] private static const bmpRoof:Class;		
		private static const wallTexture:Texture = new Texture(new bmpWall().bitmapData, "wall");
		private static const roofTexture:Texture = new Texture(new bmpRoof().bitmapData, "roof");
		
		public function TexturedHouse(name:String=null) {
			super(name);
		}
		
		/**
		 * @inheritDoc
		 */		
		override protected function setMaterials():void {
			setMaterialToSurface(new FillMaterial(0x666666), "roof_bottom");
			setMaterialToSurface(new FillMaterial(0x666666), "box_bottom");

			setUVs();
			setMaterialToSurface(new TextureMaterial(wallTexture), "walls");
			setMaterialToSurface(new TextureMaterial(roofTexture), "roof");
		}
		
		/**
		 * Mapping UV for house box and roof
		 */
		private function setUVs():void {
			// Texture fills the wall by height
			var wallsReferenceHeight:Number = wallsHeight;
			// U-coordinates of right walls' sides. First coordinate is for northern and southern walls, second is for western and eastern ones
			var wallU:Array = [houseWidth / wallsReferenceHeight, houseLength / wallsReferenceHeight];
			// Northern and southern roof slopes' height
			var snSlopeHeight:Number = getHypotenuse(roofHeight, (roofBottomLength - roofTopLength) / 2);
			// Western and eastern roof slopes' height
			var weSlopeHeight:Number = getHypotenuse(roofHeight, (roofBottomWidth - roofTopWidth) / 2);
			// Texture fills whole nortern or southern slope by height
			var roofReferenceHeight:Number = snSlopeHeight;
			// U-coordinates of lower-right vertices of the roof slope. First coordinate is for northern and southern slope, second is for eastern and western one
			var roofBottomU:Array = [roofBottomWidth / roofReferenceHeight, roofBottomLength / roofReferenceHeight];
			// U-coordinates for upper-right vertices of the roof slope. First coordinate is for northern and southern slope, second is for eastern and western one
			var roofTopU:Array = [0.5 * (roofBottomWidth + roofTopWidth) / roofReferenceHeight, 0.5 * (roofBottomLength + roofTopLength) / roofReferenceHeight];
			// V-coordinates for upper vertices of the roof slope. First coordinate is for northern and southern slope, second is for eastern and western one
			var roofTopV:Array = [1, weSlopeHeight / roofReferenceHeight];
			
			// Running over plane XY quadrants, beginning from zero
			for (var i:int = 0; i < 4; i++) {
				// wall mapping
				// U-coordinate of wall right side
				var u:Number = wallU[i & 1];
				setUVsToFace(new Point(0, 0), new Point(u, 0), new Point(u, 1), "wall_" + i);
				// roof slope mapping
				setUVsToFace(new Point(0, 0), new Point(roofBottomU[i & 1], 0), new Point(roofTopU[i & 1], roofTopV[i & 1]), "roof_slope_" + i);
			}
			// upper roof side mapping
			setUVsToFace(new Point(0, 0), new Point(roofTopLength / roofReferenceHeight, 0), new Point(roofTopLength / roofReferenceHeight, roofTopWidth / roofReferenceHeight), "roof_top");
		}
		
		/**
		 *
		 */
		private function getHypotenuse(a:Number, b:Number):Number {
			return Math.sqrt(a * a + b * b);
		}
	}
}